﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PotentialRentals.Models;
using PotentialRentals.DAL;
using PotentialRentals.Repositories;
using GoogleMaps;

namespace PotentialRentals.Controllers
{ 
    public class RentalController : Controller
    {
        private UnitOfWork _context;

        public RentalController()
        {
            _context = new UnitOfWork(null);
        }

        //
        // GET: /Rental/

        public ViewResult Index()
        {
            return View();
        }

        //
        // GET/POST: /Rental/UserList

        public ActionResult UserList()
        {
            return PartialView();
        }

        //
        // GET: /Rental/AllRentals

        public ActionResult AllRentals()
        {
            return PartialView();
        }

        //
        // GET: /Rentals/AllRentals

        public ActionResult Filter()
        {
            ViewBag.States = new SelectList(_context.StateList, "StateId", "Name");
            ViewBag.Bedrooms = new SelectList(_context.BedroomList);
            ViewBag.Bathrooms = new SelectList(_context.BathroomList);
            ViewBag.RentalTypes = new SelectList(_context.RentalTypes, "RentTypeId", "Name");

            return PartialView();
        }

        //
        // POST: /Rental/FilterAllRentals

        public ActionResult FilterAllRentals(RentalListViewModel rentalList, string incFilter)
        {
            //Disregard filter if it hasn't been submitted first
            if (incFilter == "false")
            {
                rentalList.Filter = new RentalFilter();
            }

            rentalList.Rentals = _context.RentalRepo.GetAll();

            rentalList.ProcessList();

            return PartialView(rentalList.Rentals);
        }

        //
        // POST: /Rental/FilterAllRentals

        public ActionResult FilterUserRentals(RentalListViewModel rentalList, string incFilter)
        {
            //Disregard filter if it hasn't been submitted first
            if (incFilter == "false")
            {
                rentalList.Filter = new RentalFilter();
            }

            if (User.Identity.IsAuthenticated)
            {
                var user = _context.GetUser(User.Identity.Name);
                rentalList.Rentals = user.Rentals.ToList();
            }
            else
            {
                rentalList.Rentals = Session["Rentals"] != null ? (List<Rental>)Session["Rentals"] : new List<Rental>();
            }

            rentalList.ProcessList();

            return PartialView(rentalList.Rentals);
        }

        //
        // GET: /Rental/Create

        public ActionResult Create()
        {
            ViewBag.States = new SelectList(_context.StateList, "StateId", "Name");
            ViewBag.Bedrooms = new SelectList(_context.BedroomList);
            ViewBag.Bathrooms = new SelectList(_context.BathroomList);
            ViewBag.RentalTypes = new SelectList(_context.RentalTypes, "RentTypeId", "Name");
            ViewBag.RentalAmenityList = new MultiSelectList(_context.RentalAmenityList, "AmenityId", "Name");

            return PartialView();
        }

        //
        // POST: /Rental/CreateConfirm

        [HttpPost]
        public ActionResult ConfirmAddress(Rental rental, int[] rentalAmenityList)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    #region Address Lookup

                    var addressList = new List<Address>();

                    var stateAbbr = _context.StateList.Single(x => x.StateId == rental.Address.State.StateId).Abbr;

                    var gLookup = new GoogleLookup(rental.Address.Street, rental.Address.City, stateAbbr);

                    foreach (var gAddress in gLookup.AddressResults)
                    {
                        //Check for existing before creating a new one?
                        var address = new Address()
                        {
                            Street = gAddress.Street,
                            City = gAddress.City,
                            State = _context.StateList.Single(x => x.Abbr == gAddress.State),
                            Zip = Convert.ToInt32(gAddress.Zip),
                            Lat = gAddress.Lat,
                            Lng = gAddress.Lng
                        };
                        
                        addressList.Add(address);
                    }

                    ViewBag.AddressResults = addressList;

                    #endregion

                    ViewBag.StateAbbr = stateAbbr;
                    ViewBag.RentalAmenityList = new MultiSelectList(_context.RentalAmenityList, "AmenityId", "Name", rentalAmenityList);
                    ViewBag.AddressAmenityList = new MultiSelectList(_context.AddressAmenityList, "AmenityId", "Name");

                    return PartialView(rental);
                }

                return RedirectToAction("Create", rental);
            }
            catch (Exception e)
            {
                TempData["failure"] = "There was a problem.";
                return RedirectToAction("Create", rental);
            }
        }

        //
        // POST: /Rental/Create

        [HttpPost]
        public ActionResult Create(Rental rental, int[] rentalAmenityList, int[] addressAmenityList)
        {
            try
            {
                var user = _context.GetUser(User.Identity.Name);
                rental.Owner = user;

                user.Rentals.Add(rental);

                #region Add objects
                rental.Type = _context.RentalTypes.Single(x => x.RentTypeId == rental.Type.RentTypeId);
                rental.Address.State = _context.StateList.Single(x => x.StateId == rental.Address.State.StateId);


                if (rentalAmenityList != null)
                {
                    foreach (int id in rentalAmenityList)
                    {
                        rental.Amenities.Add(_context.RentalAmenityList.Single(x => x.AmenityId == id));
                    }
                }
                if (addressAmenityList != null)
                {
                    foreach (int id in addressAmenityList)
                    {
                        rental.Address.Amenities.Add(_context.AddressAmenityList.Single(x => x.AmenityId == id));
                    }
                }
                #endregion

                if (ModelState.IsValid)
                {
                    if (User.Identity.IsAuthenticated)
                    {
                        
                        _context.Save();
                    }
                    else
                    {
                        //Create if not exists
                        var rentalList = Session["Rentals"] != null ? (List<Rental>)Session["Rentals"] : new List<Rental>();

                        rentalList.Add(rental);
                        Session["Rentals"] = rentalList;
                    }

                    TempData["success"] = "Successfully created the rental.";

                    return RedirectToAction("Create");
                }

                return PartialView(rental);
            }
            catch (Exception e)
            {
                TempData["failure"] = "There was a problem creating the Rental";
                return PartialView("ConfirmAddress", rental);
            }
        }
        
        //
        // GET: /Rental/Edit/5
        
        public ActionResult Edit(int id)
        {
            var rental = _context.RentalRepo.GetRental(id);

            if (rental.Owner.UserName == User.Identity.Name)
            {
                ViewBag.RentalAmenityList = new MultiSelectList(_context.RentalAmenityList, "RentalAmenityId", "Name", rental.Amenities);
                ViewBag.AddressAmenityList = new MultiSelectList(_context.AddressAmenityList, "AddressAmenityId", "Name", rental.Address.Amenities);
                ViewBag.Bedrooms = new SelectList(_context.BedroomList, rental.Bedrooms.ToString());
                ViewBag.Bathrooms = new SelectList(_context.BathroomList, String.Format("{0:0.##}", rental.Bathrooms));
                ViewBag.RentTypes = new SelectList(_context.RentalTypes, "RentTypeId", "Name", rental.Type.RentTypeId);
                ViewBag.States = new SelectList(_context.StateList, "StateId", "Name", rental.Address.State.StateId);

                return View(rental);
            }
            else
            {
                return View();
            }
        }

        //
        // POST: /Rental/Edit/5

        [HttpPost]
        public ActionResult Edit(Rental rental)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    //Add DB Saving Logic

                    return RedirectToAction("Index");
                }
                return View(rental);
            }
            catch
            {
                return View(rental);
            }
        }

        //
        // POST: /Rental/Add

        [HttpPost]
        public void Add(int id)
        {
            try
            {
                var rental = _context.RentalRepo.GetRental(id);
                if (rental != null)
                {
                    if (User.Identity.IsAuthenticated)
                    {
                        var user = _context.GetUser(User.Identity.Name);

                        if (user.Rentals.Contains(rental))
                        {
                            TempData["failure"] = "You already have that.";
                            return;
                        }

                        user.Rentals.Add(rental);
                        _context.Save();
                    }
                    else
                    {
                        var rentalList = Session["Rentals"] != null ? (List<Rental>)Session["Rentals"] : new List<Rental>();
                        if (rentalList.Exists(x => x.RentalId == rental.RentalId))
                        {
                            TempData["failure"] = "You already have that.";
                            return;
                        }
                        rentalList.Add(rental);
                        Session["Rentals"] = rentalList;
                    }
                    TempData["success"] = "Successfully added.";
                }
            }
            catch (Exception e)
            {
                TempData["failure"] = "Could not add.";
            }
        }

        //
        // POST: /Rental/Remove

        [HttpPost]
        public void Remove(int id, string address, int? bedrooms, int? bathrooms, int? rent) //Look into making this an object (Rental?)
        {
            try
            {
                if (User.Identity.IsAuthenticated)
                {
                    var rental = _context.RentalRepo.GetRental(id);
                    var user = _context.GetUser(User.Identity.Name);

                    if (rental != null)
                    {
                        user.Rentals.Remove(rental);
                        _context.Save();
                        TempData["success"] = "Successfully removed.";
                    }
                }
                else
                {
                    var rentalList = (List<Rental>)Session["Rentals"];
                    Rental rental;

                    if (id > 0)
                    {
                        rental = rentalList.Single(x => x.RentalId == id);
                    }
                    else
                    {
                        //For referencing Session-Created Rentals with no id
                        rental = rentalList.Find(x => x.Address.Street == address && x.Bedrooms == bedrooms && x.Bathrooms == bathrooms && x.Rent == rent);
                    }

                    if (rental != null)
                    {
                        rentalList.Remove(rental);
                        Session["Rentals"] = rentalList;
                        TempData["success"] = "Successfully removed.";
                    }
                    else
                    {
                        TempData["failure"] = "Couldn't match Rental";
                    }
                }
            }
            catch (Exception e)
            {
                TempData["failure"] = "Could not remove.";
            }
        }

        //
        // POST: /Rental/Delete/5

        [HttpPost]
        public ActionResult Delete(int id)
        {
            try
            {
                var rental = _context.RentalRepo.GetRental(id);
                if (rental.Owner.UserName == User.Identity.Name && rental != null)
                {
                    _context.RentalRepo.Delete(rental.RentalId);
                    _context.Save();
                }

                TempData["success"] = "Address deleted";
                return RedirectToAction("Index");
            }
            catch
            {
                TempData["failure"] = "Could not delete.";
                return View();
            }
        }

        protected override void Dispose(bool disposing)
        {
            _context.Dispose();
            base.Dispose(disposing);
        }
    }
}